#pragma once
#include <iostream>
#include <string>
#include <memory>
#include "Socket.hpp"
#include <jsoncpp/json/json.h>
#include <functional>
// 实现一个自定义的网络版本的计算器

using namespace SocketMoudle;
// 自定义协议
// 协议(基于TCP的)
// 1. request和response必须得有序列化和反序列化功能
class Request
{
public:
    Request()
    {
    }
    Request(int x, int y, char oper) : _x(x), _y(y), _oper(oper)
    {
    }
    std::string Serialize() // 序列化
    {
        Json::Value root;
        root["x"] = _x;
        root["y"] = _y;
        root["oper"] = _oper;
        Json::FastWriter writer;
        std::string s = writer.write(root);
        return s;
    }
    bool Deserialize(std::string &in) // 反序列化
    {
        Json::Value root;
        Json::Reader reader;
        bool ok = reader.parse(in, root);
        if (ok)
        {
            _x = root["x"].asInt();
            _y = root["y"].asInt();
            _oper = root["oper"].asInt();
        }
        return ok;
    }
    ~Request()
    {
    }
    int X() { return _x; }
    int Y() { return _y; }
    char Oper() { return _oper; }

private:
    int _x;
    int _y;
    char _oper; // + - * / % -> _x _oper _y -> 10 + 20
};
class Response
{
public:
    Response()
    {
    }
    Response(int result, int code) : _result(result), _code(code)
    {
    }
    std::string Serialize() // 序列化
    {
        Json::Value root;
        root["result"] = _result;
        root["code"] = _code;
        Json::FastWriter writer;
        std::string s = writer.write(root);
        return s;
    }
    bool Deserialize(std::string &in) // 反序列化
    {
        Json::Value root;
        Json::Reader reader;
        bool ok = reader.parse(in, root);
        if (ok)
        {
            _result = root["result"].asInt();
            _code = root["code"].asInt();
        }
        return ok;
    }
    void ShowResult()
    {
        std::cout << "计算结果是: " << _result << "[" << _code << "]" << std::endl;
    }
    ~Response()
    {
    }
    void SetResult(int res)
    {
        _result = res;
    }
    void SetCode(int code)
    {
        _code = code;
    }

private:
    int _result;
    int _code; // 0:sucess, 1,2,3,4->不同的运算异常的情况,自己规定的
};

// 2读到完整的请求(TCP)
const std::string sep = "\r\n";
using func_t = std::function<Response(Request &q)>;
class Protocol
{
public:
    Protocol()
    {}
    Protocol(func_t func) : _func(func)
    {
    }
    // 需要遵守传输协议，规定每个json请求需要前面加个字节报头来代表该请求报文的字节大小(程序员自己规定)
    // 一个完整报文例子50\r\n{"x": 10, "y" : 20, "oper" : '+'}\r\n

    std::string Encode(const std::string jsonstr) // 拼接成自己规定的完整报文
    {
        // 将json网络序列转化为自己规定的报文字符串
        int len = jsonstr.size();
        return std::to_string(len) + sep + jsonstr + sep;
    }
    bool Decode(std::string &buffer, std::string *package) // 检查报文完整性，并提取出来
    {
        ssize_t pos = buffer.find(sep);
        if (pos == std::string::npos)
        {
            return false;
        }
        // 代表至少有一个报文长度
        std::string package_len_str = buffer.substr(0, pos);
        // 接下来判断报文是否完整
        int stdlen = sep.size() * 2 + std::stoi(package_len_str) + package_len_str.size(); // 一个标准报文的长度
        if (buffer.size() < stdlen)
        {
            return false;
        }
        // 此刻buffer一定至少有一个完整的报文
        *package = buffer.substr(pos + sep.size(), stoi(package_len_str));
        buffer.erase(0, stdlen);
        return true;
    }
    void GetRequest(std::shared_ptr<Socket> &sock, InetAddr &client) // 获取请求
    {
        std::string buffer_queue;
        while (true)
        {
            // 读取
            int n = sock->Recv(&buffer_queue);
            if (n > 0)
            {
                // 检查报文并提取出来
                std::string json_package;
                bool k = Decode(buffer_queue, &json_package);
                if (!k)
                {
                    continue; // 没有读取到规定的完整报文
                }
                // 反序列化
                Request req;
                bool ok = req.Deserialize(json_package);
                if (!ok)
                {
                    continue;
                }
                // 执行请求，至于让请求实现什么任务，不关心，实现解耦
                Response resp = _func(req);
                // 将得到的回应序列化
                std::string json_str = resp.Serialize();
                // 添加自己规定的报头长度
                std::string send_str = Encode(json_str);
                // 写入/发送回应
                sock->Send(send_str);
            }
            else if (n == 0)
            {
                LOG(loglevel::INFO) << "client:" << client.StringAddr() << "Quit!";
                break;
            }
            else
            {
                LOG(loglevel::WARNING) << "client:" << client.StringAddr() << ", recv error";
                break;
            }
        }
    }
    bool GetResponse(std::shared_ptr<Socket> &client, std::string &resp_buff, Response *resp)
    {
        while (true)
        {
            int n = client->Recv(&resp_buff);
            if (n > 0)
            {
                std::string json_package;
                while (Decode(resp_buff, &json_package))
                {
                    //反序列化
                     resp->Deserialize(json_package);
                }
                return true; 
            }
            else if (n == 0)
            {
                std::cout << "server quit " << std::endl;
                return false;
            }
            else
            {
                std::cout << "recv error" << std::endl;
                return false;
            }
        }
    }
     std::string BuildRequestString(int x, int y, char oper)//构建请求字符串
     {
        //构建一个完整的请求
        Request req(x, y, oper);
         // 序列化
        std::string json_req = req.Serialize();
        //添加报头
        return Encode(json_req);
     }
    ~Protocol()
    {
    }

private:
    func_t _func;
};